﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ParkingApp.ParkingSlot.Simulator.Lib;
using ParkingApp.Common;
namespace ParkingApp.Lib
{
    public class Parking : IParking
    {
        ParkingSlotAvailabilitySimulator _simulatorInstance;

        ParkingSlotAvailabilitySimulator SimulatorInstance {
            get {
                _simulatorInstance = CachingService.Get<ParkingSlotAvailabilitySimulator>("_simulatorInstance");
                if (_simulatorInstance == null)
                {
                    _simulatorInstance = new ParkingSlotAvailabilitySimulator();
                    CachingService.AddItem("_simulatorInstance", _simulatorInstance);
                    return _simulatorInstance;
                }
                else return _simulatorInstance;
            }
        }

        public Slot GetAvailableSlot() {
            var availableSlots = SimulatorInstance.GetAvailableSlots();
            if (availableSlots.Count != 0) return availableSlots[0];
            else throw new ParkingException("No available slots.");
        }

        public TicketDetail AllocateParkingSlot(Slot parkingSlot, string plateNumber) {
            if (parkingSlot != null)
            {
                SimulatorInstance.AllocateSlot(parkingSlot);
                var ticket = new TicketDetail()
                {
                    Slot = parkingSlot,
                    PlateNumber = plateNumber,
                    DateTimeOfEntry = DateTime.Now
                };
                // TODO : Save ticket details
                return ticket;
            }
            else return null;
        }

        public TicketDetail ReAllocateParkingSlot(TicketDetail ticket)
        {
            var slot = GetAvailableSlot();
            return AllocateParkingSlot(slot, ticket.PlateNumber); 
        }

        private void TagIllegalParkedVehicle(string plateNumber)
        {
            new IllegalyParkedVehicle().AddVehicle(plateNumber);
        }

        public void MakeSlotUnavailable(Slot parkingSlot, Slot.NotAvailableReason notAvailableReason, string plateNumber)
        {
            _simulatorInstance.MakeSlotUnavailable(parkingSlot, notAvailableReason);
            if (plateNumber != null) TagIllegalParkedVehicle(plateNumber);
        }
    }
}
